package cn.com.bsoft.kotlinEx

import org.apache.http.client.methods.HttpGet
import org.apache.http.client.methods.HttpPost
import org.apache.http.client.methods.HttpUriRequest
import org.apache.http.entity.ByteArrayEntity
import org.apache.http.impl.client.CloseableHttpClient
import org.apache.http.impl.client.HttpClients
import org.apache.http.util.EntityUtils
import java.io.*
import java.net.URL

typealias HttpPostInitHandler = (HttpPost) -> Unit

fun httpClient(): CloseableHttpClient {
    return HttpClients.createDefault()
}

fun URL.execute(request: HttpUriRequest):InputStream{
    return httpClient().use {
        httpClient ->
        httpClient.execute(request).use {
            response ->
            val responseEntity = response.entity
            if (response.statusLine.statusCode > 400) {
                val msg = EntityUtils.toString(responseEntity)
                println("msg:$msg")
                throw StatusAndMessageError(-1,msg)
            }else {
                val bytes = EntityUtils.toByteArray(responseEntity)
                println(String(bytes, Charsets.UTF_8))
                ByteArrayInputStream(bytes)
            }

        }
    }
}

fun URL.post(body: (out: OutputStream) -> Unit,
             initHandler: HttpPostInitHandler? = null): InputStream {
    val byteArrayOutputStream = ByteArrayOutputStream()

    body(byteArrayOutputStream)

    byteArrayOutputStream.flush()

    val httPost = HttpPost(this.toURI())
    val entity = ByteArrayEntity(byteArrayOutputStream.toByteArray())
    httPost.entity = entity

    if (initHandler != null) initHandler(httPost)

    return execute(httPost)
}

fun URL.get(initHandler: ((httpGet: HttpGet) -> Unit)? = null): InputStream {

    val httpGet = HttpGet(this.toURI())

    if (initHandler != null) initHandler(httpGet)

    return execute(httpGet)
}

fun  URL.ajax(obj:Any?, handler: HttpPostInitHandler):InputStream{
    //val javaType = T::class.javaType

    val input =post({
        out ->
        objectMapper().writeValue(out,obj)
    },handler)

    return input
}